#pragma once
#include <vector>
#include "Cond.hpp"
#include "Mutex.hpp"
#include "Sem.hpp"

using namespace Cond_module;
using namespace Mutex_module;
using namespace Semaphore_module;

template <typename T>
class RingQueue
{
public:
    static const int max_cap = 5;
    RingQueue()
        : _cap(max_cap), _cstep(0), _pstep(0), _csem(0), _psem(max_cap)
    {
        _ringQueue.resize(_cap);
    }
    void Consume()
    {
        _csem.Wait();
        {
            LockGuard lg(_cmut);

            auto ret = _ringQueue[_cstep++];

            _cstep %= _cap;

            _psem.Post();
        }
    }
    void Produce(const T &product)
    {
        _psem.Wait();
        {
            LockGuard lg(_pmut);

            auto ret = _ringQueue[_pstep++];
            (void)ret;

            _pstep %= _cap;

            _csem.Post();
        }
    }
    ~RingQueue()
    {
    }

private:
    std::vector<T> _ringQueue;
    int _cap;

    // int _surplus;
    // int _space;
    Sem _csem;
    Sem _psem;

    int _cstep; // 消费者的消费位置
    int _pstep; // 生产者的生产位置

    Sem _sem; // 确保生产者和消费者的同步关系;

    Mutex _cmut; // 消费者间保持串行的锁
    Mutex _pmut; // 生产者间保持串行的锁
};
